iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0

前幾天我們把系統從單一 Server 擴展成:

                     ┌── Server #1
                     │
User → Load Balancer ├── Server #2
                     │
                     └── Server #3
                              ↓
                          Database

Backend 可以 Horizontal Scaling,但所有 Server 最後仍然需要存取資料。

例如:

Customer
Product
Shopping Cart
Order
Payment

這時候就會遇到另一個重要問題:

這些資料到底應該怎麼存?

最常看到的兩個方向就是:

SQL
vs
NoSQL

今天除了 SQL / NoSQL,也會加入一組很適合台積電 IT Software Engineer 面試準備的情境:

設計 Customer、Product、Shopping Cart 與 Checkout。


SQL 是什麼?

SQL Database 通常指 Relational Database。

常見例子:

PostgreSQL
MySQL
MariaDB
Oracle
SQL Server

Relational Database 的核心特色之一是資料以 Table 組織,而且不同 Table 可以建立 Relationship。

例如:

users
id name email
1 Alvin alvin@example.com
2 Bob bob@example.com

另一張 Table:

orders
id user_id total_amount
101 1 1200
102 1 800

其中:

orders.user_id → users.id

形成:

User
  │
  └── has many → Orders

Primary Key 與 Foreign Key

例如:

CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(255)
);

id 是 Primary Key,用來唯一識別 User。

CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    total_amount DECIMAL(10, 2),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

user_id 則是 Foreign Key。

因此 SQL Database 很適合處理具有明確 Relationship 的資料。


JOIN

假設想取得 Alvin 的 Orders:

SELECT
    users.name,
    orders.id,
    orders.total_amount
FROM users
JOIN orders
    ON users.id = orders.user_id
WHERE users.id = 1;

Relationship 可能一路延伸:

Users
  ↓
Orders
  ↓
Order Items
  ↓
Products

這種 Data Model 在 E-commerce、Banking、ERP、Inventory System 都非常常見。


NoSQL 是什麼?

NoSQL 並不是單一種類的 Database。

常見 Data Model:

Document
Key-Value
Wide-Column
Graph

例如:

MongoDB   → Document
Redis     → Key-Value / Data Structure Store
Cassandra → Wide-Column
Neo4j     → Graph

以 Document Database 為例:

{
  "_id": 1,
  "name": "Alvin",
  "email": "alvin@example.com",
  "preferences": {
    "language": "zh-TW",
    "theme": "dark"
  }
}

Document Model 在某些資料結構經常變動、欄位差異大的情境下會比較自然。


SQL vs NoSQL

SQL NoSQL
Data Model Table / Row Document、Key-Value 等
Schema 通常較明確 依 Database 類型而定
Relationship 很擅長 視資料模型而定
JOIN 常見 不一定支援或不鼓勵大量 JOIN
Transaction 成熟且常見 能力依 Database 而不同
Scaling Vertical / Horizontal 都可 很多產品強調 Distributed Scaling

但不要把它背成:

SQL = 小系統
NoSQL = 大系統

大型系統同樣可以使用 SQL。

SQL Database 也能搭配:

Index
Read Replica
Partitioning
Sharding
Caching

處理大量資料與 Traffic。

所以 Database Selection 應該考慮:

Data Model?
Relationship?
Query Pattern?
Read / Write Ratio?
Transaction Requirement?
Consistency Requirement?
Expected Scale?

面試情境:Customer / Product / Shopping Cart

假設面試官說:

請設計一個 Shopping System Database,包含 Customer、Product 和 Shopping Cart。

不要馬上畫 Table。

先確認 Requirement:

一個 Customer 可以有幾個 Active Cart?
一個 Cart 可以有多少 Product?
同一 Product 可以出現在不同 Cart 嗎?
需要 Quantity 嗎?
Product Price 會改變嗎?
Checkout 後 Cart 怎麼處理?

System Design 很重要的習慣:

Requirement → Design


Customer

CREATE TABLE customers (
    id BIGINT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL
);

Product

CREATE TABLE products (
    id BIGINT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    stock INT NOT NULL
);

Shopping Cart

CREATE TABLE carts (
    id BIGINT PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    status VARCHAR(20) NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);

例如:

ACTIVE
CHECKED_OUT

Cart Items

一個 Cart 可以有很多 Product,一個 Product 也可以出現在很多 Cart。

這是:

Many-to-Many Relationship

所以建立中間 Table:

CREATE TABLE cart_items (
    cart_id BIGINT,
    product_id BIGINT,
    quantity INT NOT NULL,
    PRIMARY KEY (cart_id, product_id),
    FOREIGN KEY (cart_id) REFERENCES carts(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

Relationship:

Customer
   ↓
 Cart
   ↓
Cart Items
   ↓
Product

Checkout 才是真正困難的地方

User 按下 Checkout 時可能需要:

1. 確認 Cart
2. 確認 Inventory
3. 建立 Order
4. 建立 Order Items
5. 扣除 Inventory
6. 更新 Cart Status

概念上:

BEGIN TRANSACTION

Check Inventory
Create Order
Create Order Items
Update Inventory
Update Cart

COMMIT

如果:

Create Order     ✅
Update Inventory ❌

我們不希望留下半完成的資料。

這就需要:

Transaction


ACID

A → Atomicity
C → Consistency
I → Isolation
D → Durability

Atomicity

一組 Transaction:

要嘛全部成功,要嘛全部失敗。

全部成功 → COMMIT
任何重要步驟失敗 → ROLLBACK

Consistency

Transaction 前後都要維持 Database 定義的有效規則與 Constraint。

例如 Business Rule 不允許:

stock < 0

就不應該留下:

stock = -1

Isolation

假設:

Product A stock = 1

Alvin 和 Bob 同時 Checkout:

Alvin Transaction ─┐
                   ├── Product A
Bob Transaction ───┘

如果兩個 Transaction 同時看到:

stock = 1

兩個人都可能以為自己買得到。

這可能造成:

Overselling

這就是 Concurrent Transaction 與 Isolation 要處理的問題之一。

Durability

Transaction 成功 Commit 後,資料應該被可靠保存。

Order COMMIT
      ↓
Server Crash
      ↓
已 Commit 的 Order 不應隨意消失

面試延伸:兩個人同時買最後一個商品

這是一個很值得練習的問題:

Product 只剩最後一個,兩個 Customer 同時 Checkout 怎麼辦?

不能只寫:

if stock > 0:
    stock -= 1

因為可能發生:

Initial Stock = 1

Transaction A reads 1
Transaction B reads 1

A → Buy
B → Buy

這就是:

Race Condition / Concurrency Problem

可能需要考慮:

Database Lock
Atomic Update
Optimistic Locking
Pessimistic Locking
Isolation Level

例如概念上可以:

UPDATE products
SET stock = stock - 1
WHERE id = 101
  AND stock > 0;

再檢查:

Affected Rows = 1 → 成功

Affected Rows = 0 → 沒有庫存

這可以避免某些:

SELECT stock
    ↓
Application 判斷
    ↓
UPDATE stock

產生的 Read-Modify-Write Race Condition。


為什麼這題很適合 System Design?

一個 Checkout 可以一路延伸:

Database Schema
      ↓
Relationship
      ↓
Transaction
      ↓
ACID
      ↓
Concurrency
      ↓
Isolation
      ↓
Locking
      ↓
High Traffic
      ↓
Database Bottleneck

真正需要練習的不是只背:

SQL = Relational
NoSQL = Non-relational

而是:

從 Requirement 一步一步發現系統問題,並解釋自己的 Solution 與 Trade-off。


什麼情況可能考慮 NoSQL?

例如不同 Product 的 Metadata 差異很大:

{
  "type": "laptop",
  "cpu": "M3",
  "ram": "16GB"
}

另一種商品:

{
  "type": "shirt",
  "size": "L",
  "material": "cotton"
}

Document Database 在這類彈性 Data Model 中可能比較自然。

另外:

session:abc123
      ↓
User Session

這種 Key → Value Access Pattern 則可能適合 Key-Value Store。

所以不是:

哪個 Database 比較強?

而是:

哪個 Data Model 最符合 Requirement 與 Access Pattern?


SQL 和 NoSQL 可以一起用嗎?

可以。

例如:

Orders
Payments
Inventory
    ↓
PostgreSQL

因為重視:

Transaction
Relationship
Consistency

而:

Session
Cache
 ↓
Redis

或:

Flexible Product Metadata
        ↓
Document Database

大型系統可能根據不同 Requirement 使用不同 Storage Technology。


System Design 面試不要只回答 SQL 或 NoSQL

如果面試官問:

你會選 SQL 還是 NoSQL?

先思考:

Data Model?
Relationship?
Query Pattern?
Read / Write Ratio?
Transaction Requirement?
Consistency Requirement?
Expected Scale?

然後再說明:

Based on these requirements,
I would start with PostgreSQL because...

重點不是猜面試官想聽哪個 Database。

而是:

說明你的選擇,以及 Trade-off。

仍然回到這個 Framework:

Problem
   ↓
Requirement
   ↓
Solution
   ↓
Trade-off

台積電面試準備 Checkpoint

今天可以直接練習:

1. 請設計 Customer、Product、Shopping Cart 的 Database Schema。

2. Customer 和 Cart 是什麼 Relationship?

3. Cart 和 Product 是什麼 Relationship?

4. 為什麼需要 cart_items?

5. Checkout 時需要哪些 Database Operations?

6. 什麼是 Transaction?

7. ACID 分別代表什麼?

8. Checkout 中途失敗怎麼辦?

9. 只剩最後一個 Product,
   兩個 User 同時 Checkout 怎麼辦?

10. Isolation 解決什麼問題?

11. 這個系統會選 SQL 還是 NoSQL?
    Why?

12. Traffic 增加後 Database 變成 Bottleneck,
    下一步會怎麼處理?

如果能不看答案,用自己的話完整講出這些問題,今天就同時完成:

鐵人賽 Day 5
+
System Design 基礎
+
台積電 IT 面試複習

今天學到了什麼?

SQL 很適合處理:

Structured Data
Relationship
JOIN
Transaction
Data Integrity

NoSQL 則包含:

Document
Key-Value
Wide-Column
Graph

選擇 Database 時,不要只看資料量。

應該從:

Requirement
Data Model
Query Pattern
Transaction
Consistency
Scale

一起考慮。

另外,Shopping Cart / Checkout 讓我們開始接觸:

Transaction
ACID
Concurrency
Isolation
Race Condition

這些觀念之後還會繼續出現在更完整的 System Design 裡。


下一篇

當資料量從:

1,000 rows
    ↓
1,000,000 rows
    ↓
100,000,000 rows

Query 可能開始變慢。

例如:

SELECT *
FROM users
WHERE email = 'alvin@example.com';

Database 要怎麼快速找到資料?

下一篇:

Day 6|Database Index:為什麼加一個 Index,Query 可以快這麼多?

會開始了解:

Full Table Scan
Index
B-Tree
Read Performance
Write Cost
Composite Index

並延伸:

為什麼 Database Query 很慢?
怎麼找 Database Bottleneck?
什麼情況應該加 Index?
為什麼不能每個 Column 都加 Index?

再一步一步進入:

Database Optimization
Cache
Read Replica
Sharding

上一篇
# Day 4|Load Balancer 是什麼?多台 Server 到底要怎麼分配 Request?
下一篇
# Day 6|Database Index:為什麼加一個 Index,Query 可以快這麼多?
系列文
30 天從 Full-Stack Engineer 進化到 System Design:從 0 設計可支撐百萬使用者的系統9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言